#!/bin/bash
SCRIPT=$(readlink -f "$0")
INSTALLPATH=$(dirname "${SCRIPT}")
TOPDIR=$(dirname "${INSTALLPATH}")
DATASDIR=${TOPDIR}/datas/

inifile=${INSTALLPATH}/settings.ini
handle_ini_py=${INSTALLPATH}/handle_ini.py
sections=$(python3 "${handle_ini_py}" "${inifile}" get_sections string)  # 获取ini文件里面的所有节

help_text="
    Usage:
    ./$(basename $0) 显示本信息
    ./$(basename $0) all|project [start|stop|restart|init]

    Debug:
    ./$(basename $0) project [debug|shell|runserver]

    * 第一个参数如果为all表示对所有项目执行指令，Debug分类下的指令不能为all。
    * init 指令是在首次部署项目时使用，会调用项目的初始化脚本，自动创建核心数据等，如果在初始化后再次调用该指令不会执行任何操作
"

# 判断用户输入的参数数量是否正确
if [[ $# < 1 ]]; then
    echo "$help_text";
    exit 1;
# 判断用户输入的项目是否有效
elif [[ $1 != "all" && `python3 "${handle_ini_py}" "${inifile}" in_sections $1` == "False" ]]; then
    echo "输入的项目不存在"
    exit 1;
fi

# 判断用户输入的指令是否有效，并判断是否是Debug选项
if [[ $2 == "start" || $2 == "stop" || $2 == "restart" || $2 == "init" ]]; then
    debug_command=0
elif [[ $2 == "debug" || $2 == "shell" || $2 == "runserver" || $2 == "check" ]]; then
    if [[ $1 == "all" ]]; then
        echo "debug类指令不允许指定项目为all";
        exit 1;
    fi
    debug_command=1
else
    echo "输入的指令不存在"
    echo "$help_text"
fi

export PROJECT_SETTINGS_DIR=${INSTALLPATH}

project_input=$1
run_command=$2

if [[ ! -d "${DATASDIR}" ]]; then
    mkdir -p ${DATASDIR}
fi
# 创建日志文件夹
if [[ ! -d "${DATASDIR}/logs" ]]; then
    mkdir ${DATASDIR}/logs
fi
if [[ ! -d "${DATASDIR}/db" ]]; then
    mkdir ${DATASDIR}/db
fi
touch ${DATASDIR}/inited;

function validate_port () {
    if ! [[ ${port} =~ ^[1-9][0-9]{1,4}$ ]] ; then
        printf "\033[033m${port}\033[m is not a valid port number\n\n"
        exit 1
    fi
}

if [[ $run_command == "debug" || $run_command == "runserver" ]]; then
    # 大于等于
    if [[ $# -ge 3 ]]; then
        port=$3
        validate_port
        # 获取第三个及以后的参数
        shift
        shift
        shift
        other_args=$*
    else
        port=8091
        shift
        shift
        other_args=$*
    fi
fi

function before_start() {
    # Migrate database
    python3 ${manage_py} makemigrations 1>> ${DATASDIR}/logs/${project}_service.log
    python3 ${manage_py} migrate 1>> ${DATASDIR}/logs/${project}_service.log
    python3 ${manage_py} clearsessions 1>> ${DATASDIR}/logs/${project}_service.log
    echo "yes" | python3 ${manage_py} collectstatic 1>> ${DATASDIR}/logs/${project}_service.log
#    python3 ${manage_py} upgrade
}

function validate_project_running () {
    if pgrep -f "${manage_py}" 2>/dev/null 1>&2; then
        echo "[${project}] Application is already running."
        return 2;
    elif pgrep -f "${project_dir}/gunicorn.conf.py" 2>/dev/null 1>&2; then
        echo "[${project}] Application is already running."
        return 2;
    fi
}

function init_project () {
    if [[ `cat ${DATASDIR}/inited | grep -w ${project}` ]]; then
        echo "The project '${project}' has been initialized, skip initialization";
    else
        echo "Init Project '${project}'"
        bash ${project_dir}/init_project.sh
        if [ $? -eq 0 ]; then
            echo "${project}" >> ${DATASDIR}/inited
        fi
    fi
}

function start_project () {
    validate_project_running;
    if [[ $? == 2 ]]; then
      return 2;
    fi

    echo "[${project}] Starting project ..."

    before_start;
    gunicorn -c ${project_dir}/gunicorn.conf.py --preload;

    sleep 3;

    if ! pgrep -f "${project_dir}/gunicorn.conf.py" 2>/dev/null 1>&2; then
        printf "\033[33m[${project}] Error:Project failed to start.\033[m\n"
        echo "Please try to run \"$(basename $0) start\" again"
    else
        echo "[${project}] Project start successful."
    fi
}

function stop_project () {
    if [[ -f ${pidfile} ]]; then
        echo "[${project}] Stopping project ..."
        pkill -9 -f "${project_dir}/gunicorn.conf.py"
        sleep 1
        if pgrep -f "${project_dir}/gunicorn.conf.py" 2>/dev/null 1>&2 ; then
            echo '[${project}] Failed to stop project.'
            exit 1
        fi
        rm -f ${pidfile}
        return 0
    else
        echo "[${project}] Project is not running"
    fi
}

function restart_project() {
    stop_project;
    sleep 2
    start_project;
}

function debug_mode() {
    validate_project_running;

    before_start;
    gunicorn -c ${project_dir}/gunicorn.debug.py --preload;
}

function django_shell() {
    before_start;
    python3 ${manage_py} shell
}

function runserver() {
    before_start;
    python3 ${manage_py} runserver 0.0.0.0:${port} ${other_args};
}

function check_project() {
    before_start;
    python3 ${manage_py} check;
}

function execute_command() {
    project_dir=${TOPDIR}/${project}/
    manage_py=${project_dir}/manage.py
    pidfile=${DATASDIR}/${project}.pid
    echo "[`date`] Executed: ${run_command} ${other_args}" >> ${DATASDIR}/logs/${project}_service.log
    case ${run_command} in
        "start" )
            start_project;
            ;;
        "stop" )
            stop_project;
            ;;
        "restart" )
            restart_project;
            ;;
        "init" )
            init_project;
            ;;
        "debug" )
            debug_mode;
            ;;
        "shell" )
            django_shell;
            ;;
        "runserver" )
            runserver;
            ;;
        "check" )
            check_project;
            ;;
    esac
}

if [[ $project_input == "all" ]]; then
    # 分词
    IFS_OLD=$IFS
    IFS=$' '
    for project in $sections
    do
        execute_command
    done
    IFS=$IFS_OLD
else
    project=$project_input
    execute_command
fi
